package org.jsola.hr.service.impl.notice;


import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsola.cache.ICache;
import org.jsola.common.*;
import org.jsola.contract.common.CacheKeyKit;
import org.jsola.contract.dto.SignWeiXinSendDTO;
import org.jsola.contract.entity.ContractDO;
import org.jsola.hr.common.DateUtils;
import org.jsola.hr.common.NoticeKit;
import org.jsola.hr.common.wechat.JumpWxa;
import org.jsola.hr.common.wechat.MessageHandlerUtil;
import org.jsola.hr.constant.ConfigCodeConstants;
import org.jsola.hr.constant.EmpInfoStatus;
import org.jsola.hr.constant.FormalTypeEnum;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.entity.*;
import org.jsola.hr.provider.*;
import org.jsola.hr.service.*;
import org.jsola.hr.service.notice.ISendNoticeService;
import org.jsola.hr.vo.CompanyVO;
import org.jsola.hr.vo.EmpChangesVO;
import org.jsola.message.dto.ShortMessageDTO;
import org.jsola.message.dto.WeiXinDTO;
import org.jsola.message.dto.WxMiNiParam;
import org.jsola.message.dto.WxTemplateParam;
import org.jsola.notice.constant.EmpType;
import org.jsola.notice.constant.NoticeConstants;
import org.jsola.notice.constant.ReceiveDateTypeEnum;
import org.jsola.notice.constant.WayType;
import org.jsola.notice.dto.UserNoticeAddDTO;
import org.jsola.notice.vo.NoticeRuleSettingVO;
import org.jsola.user.core.TokenUser;
import org.jsola.user.entity.UnionOpenIdDO;
import org.jsola.user.entity.UserDO;
import org.jsola.user.vo.UserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

import static org.jsola.contract.constant.ContractConstants.*;
import static org.jsola.contract.constant.ContractConstants.CODE_PATH_CONTRACTSIGN;

@Slf4j
@Service("hrSendNoticeServiceImpl")
public class SendNoticeServiceImpl implements ISendNoticeService {

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private IEmpChangesService empChangesService;

    @Autowired
    private ICompanyService companyService;

    @Autowired
    private INoticeProviderService noticeProviderService;

    @Autowired
    private IMessageProviderService messageProviderService;

    @Autowired
    private ISiteConfigProviderService siteConfigProviderService;

    @Autowired
    private IUserProviderService userProviderService;

    @Autowired
    private IContractProviderService contractProviderService;

    @Autowired
    private IEmpContractService empContractService;

    @Autowired
    private IEmpPaperContractService empPaperContractService;

    @Autowired
    private ICompanySaleServerService companySaleServerService;

    @Autowired
    private ICache cache;


    /**
     * 跳转地址-员工异动
     */
    private static final String TO_URL_PERSONNEL = "/staff/manger";

    /**
     * 跳转地址-增减员确认
     */
    private static final String TO_URL_SOC = "/shebao/shebaoManage/shebaoZengJianY";

    /**
     * 跳转地址-事件处理
     */
    private static final String TO_URL_EVENT_HANDLING = "/admin/eventHandling";

    /**
     * 跳转地址-甲方合同
     */
    private static final String TO_URL_JF_CONTRACT = "/admin/add_employment_unit?id=";

    /**
     * 跳转地址-签署记录
     */
    private static final String TO_URL_CONTRACT = "/contract/elecontract";

    /**
     * 员工id
     */
    private static final Integer EMP_TYPE = 1;

    /**
     * 员工变动记录id
     */
    private static final Integer EMP_CHANGE_TYPE = 2;

    @Override
    public void sendPersonnelNotice(String subjectIds, Integer idType, String noticeTypeCode, Boolean isFixedNotice) {
        String[] split = subjectIds.split(",");
        List<String> subjectIdList = Arrays.asList(split);
        List<String> empIdList = new ArrayList<>();
        // 员工id
        if (EMP_TYPE.equals(idType)) {
            empIdList = subjectIdList;
        }
        // 员工变动记录id
        else if (EMP_CHANGE_TYPE.equals(idType)) {
            List<EmpChangesDO> empChangesDOS = empChangesService.selectByIdList(subjectIdList);
            empIdList = empChangesDOS.stream().map(EmpChangesDO::getEmpId).collect(Collectors.toList());
        }
        List<EmpInfoDO> empInfoDOList = empInfoService.selectDoByIds(empIdList);

        if (CollectionUtils.isEmpty(empInfoDOList)) {
            log.info("发送失败：员工信息不存在，noticeTypeCode:{}，empInfoDOList：{}", noticeTypeCode, JSON.toJSONString(empInfoDOList));
            return;
        }

        String siteId = empInfoDOList.get(0).getSiteId();
        String empId = empInfoDOList.get(0).getId();
        String empName = empInfoDOList.get(0).getName();
        String companyId = empInfoDOList.get(0).getCompanyId();
        TokenUser tokenUser = new TokenUser();
        tokenUser.setUserId("system");
        tokenUser.setSiteId(siteId);
        // 校验员工变更记录
        String empChangeId = null;
        if (EMP_CHANGE_TYPE.equals(idType)) {
            empChangeId = subjectIdList.get(0);
        }
        // 校验员工业务状态
        if (!checkEmpChange(empId, empChangeId, siteId, noticeTypeCode)) {
            log.info("发送失败：校验员工变更记录不通过，noticeTypeCode：{},empId:{},empChangeId:{}", noticeTypeCode, empId, empChangeId);
            return;
        }
        CompanyVO companyVO = companyService.selectBaseCompanyById(empInfoDOList.get(0).getCompanyId(), tokenUser.getSiteId());
        // 用工单位名称
        String companyName = companyVO.getName();
        NoticeRuleSettingVO ruleSettingVO = noticeProviderService.selectByTypeCodeAndCompany(HrConstants.HR_SUBJECT_TYPE,
                noticeTypeCode, companyId);

        if (Objects.isNull(ruleSettingVO)) {
            log.info("发送失败：通知设置不存在，noticeTypeCode：{},companyId:{}", noticeTypeCode, companyId);
            return;
        }
        // 需要发送的userId
        List<String> userIdList = NoticeKit.getNoticeUserId(empId, ruleSettingVO, tokenUser);
        if (CollectionUtils.isEmpty(userIdList)) {
            log.info("发送失败：通知设置userId不存在, code: {}, 用工单位id: {}", noticeTypeCode, companyId);
            return;
        }
        if (!ruleSettingVO.getEnableStatus()) {
            log.info("发送失败：通知设置未开启, code: {}, 用工单位id: {}", noticeTypeCode, companyId);
            return;
        }

        // 通知类型
        String receiveType = ruleSettingVO.getReceiveType();
        List<String> receiveTypeList = Arrays.asList(receiveType.split(","));
        // 微信通知
        if (receiveTypeList.contains(WayType.WEIXIN.getValue())) {
            personnelSendWeChat(empInfoDOList.get(0).getName(), empInfoDOList.size(), companyName, userIdList,
                    isFixedNotice, noticeTypeCode, tokenUser);
        }
        if (receiveTypeList.contains(WayType.SYSTEM.getValue())) {
            String toUrl = "";
            // 校验业务
            switch (noticeTypeCode) {
                // 待入职
                case NoticeConstants.PRE_INDUCTION:
                    toUrl = TO_URL_PERSONNEL + "?selectId=1&nameOrPhone=" + empName;
                    break;
                // 入职
                case NoticeConstants.INDUCTION:
                    toUrl = "/staff/employee?name=" + empName + "&companyId=" + companyId + "&companyName=" + companyName;
                    break;
                // 待转正
                case NoticeConstants.PRE_TURN_OFFICIAL:
                    toUrl = TO_URL_PERSONNEL + "?selectId=2&nameOrPhone=" + empName;
                    break;
                // 待调岗
                case NoticeConstants.PRE_TRANSFER:
                    if (subjectIdList.size() > 1) {
                        toUrl = TO_URL_PERSONNEL + "?selectId=5";
                    } else {
                        toUrl = TO_URL_PERSONNEL + "?selectId=5&nameOrPhone=" + empName;
                    }
                    break;
                // 待离职
                case NoticeConstants.PRE_RESIGN:
                    if (subjectIdList.size() > 1) {
                        toUrl = TO_URL_PERSONNEL + "?selectId=4";
                    } else {
                        toUrl = TO_URL_PERSONNEL + "?selectId=4&nameOrPhone=" + empName;
                    }
                    break;
                // 离职
                case NoticeConstants.RESIGN:
                    if (subjectIdList.size() > 1) {
                        toUrl = "/staff/employee?tag=4&companyId=" + companyId + "&companyName=" + companyName;
                    } else {
                        toUrl = "/staff/employee?name=" + empName + "&tag=4" + "&companyId=" + companyId + "&companyName=" + companyName;
                    }

                    break;
                default:
                    break;
            }
            if (Boolean.FALSE.equals(isFixedNotice)) {
                if (NoticeConstants.RETIRE.equals(noticeTypeCode)) {
                    toUrl = "";
                }
            }
            if (NoticeConstants.RETIRE.equals(noticeTypeCode)) {
                toUrl = "/staff/detail?userId=" + empInfoDOList.get(0).getUserId() + "&id=" + empInfoDOList.get(0).getId();
            }
            // 用户通知
            batchSaveByCode(userIdList, noticeTypeCode, ruleSettingVO.getNoticeTypeId(), companyId,
                    empName, empInfoDOList.size(), companyVO.getName(), toUrl, tokenUser);
        }
    }

    /**
     * 校验员工变更记录
     */
    private boolean checkEmpChange(String empId, String empChangeId, String siteId, String subjectType) {
        //退休
        if (subjectType.equals(NoticeConstants.RETIRE)) {
            EmpInfoDO empInfoDO = empInfoService.selectDOById(empId, siteId);
            if (empInfoDO == null) {
                return false;
            }
            return true;
        }
        // 待离职(empChangeId)
        if (subjectType.equals(NoticeConstants.PRE_RESIGN)) {
            EmpInfoDO empInfoDO = empInfoService.selectDOById(empId, siteId);
            if (empInfoDO == null) {
                log.error("发送失败：员工信息不存在，empId：{}", empId);
                return false;
            }
            if (!EmpInfoStatus.WAIT_QUIT.getValue().equals(empInfoDO.getStatus())) {
                log.error("发送失败：员工当前不是待离职状态，empId：{}", empId);
                return false;
            }
            EmpChangesVO empChangesVO = empChangesService.selectById(empChangeId, siteId);
            if (empChangesVO == null) {
                log.error("发送失败：员工变动记录不存在，empChangeId：{}", empChangeId);
                return false;
            } else {
                // "状态(0:初始;1:通过;2:拒绝)"
                if (0 != empChangesVO.getChangeStatus()) {
                    log.error("发送失败：员工变动记录不是初始状态，empChangeId：{}，status：{}", empChangeId, empChangesVO.getChangeStatus());
                    return false;
                }
            }
            return true;
        }
        // 离职
        else if (subjectType.equals(NoticeConstants.RESIGN)) {
            EmpInfoDO empInfoDO = empInfoService.selectDOById(empId, siteId);
            if (empInfoDO == null) {
                log.error("发送失败：员工信息不存在，empId：{}", empId);
                return false;
            }
            if (!EmpInfoStatus.HAS_QUIT.getValue().equals(empInfoDO.getStatus())) {
                log.error("发送失败：员工当前不是离职状态，empId：{}", empId);
                return false;
            }
            return true;
        }
        // 待入职
        else if (subjectType.equals(NoticeConstants.PRE_INDUCTION)) {
            EmpInfoDO empInfoDO = empInfoService.selectDOById(empId, siteId);
            if (empInfoDO == null) {
                log.error("发送失败：员工信息不存在，empId：{}", empId);
                return false;
            }
            if (!EmpInfoStatus.WAIT_ENTRY.getValue().equals(empInfoDO.getStatus())) {
                log.error("发送失败：员工当前不是待入职状态，empId：{}", empId);
                return false;
            }
            return true;
        }
        // 入职
        else if (subjectType.equals(NoticeConstants.INDUCTION)) {
            EmpInfoDO empInfoDO = empInfoService.selectDOById(empId, siteId);
            if (empInfoDO == null) {
                log.error("发送失败：员工信息不存在，empId：{}", empId);
                return false;
            }
            if (!EmpInfoStatus.HAS_ENTRY.getValue().equals(empInfoDO.getStatus())) {
                log.error("发送失败：员工当前不是在职状态，empId：{}", empId);
                return false;
            }
            return true;
        }
        // 待调岗(empChangeId)
        else if (subjectType.equals(NoticeConstants.PRE_TRANSFER)) {
            EmpInfoDO empInfoDO = empInfoService.selectDOById(empId, siteId);
            if (empInfoDO == null) {
                log.error("发送失败：员工信息不存在，empId：{}", empId);
                return false;
            }
            EmpChangesVO empChangesVO = empChangesService.selectById(empChangeId, siteId);
            if (empChangesVO == null) {
                log.error("发送失败：员工变动记录不存在，empChangeId：{}", empChangeId);
                return false;
            } else {
                // "状态(0:初始;1:通过;2:拒绝)"
                if (0 != empChangesVO.getChangeStatus()) {
                    log.error("发送失败：员工变动记录不是初始状态，empChangeId：{}，status：{}", empChangeId, empChangesVO.getChangeStatus());
                    return false;
                }
            }
            return true;
        }
        // 转正
        else if (subjectType.equals(NoticeConstants.PRE_TURN_OFFICIAL)) {
            EmpInfoDO empInfoDO = empInfoService.selectDOById(empId, siteId);
            if (empInfoDO == null) {
                log.error("发送失败：员工信息不存在，empId：{}", empId);
                return false;
            }
            if (!FormalTypeEnum.PROBATION.getValue().equals(empInfoDO.getFormalType())) {
                log.error("发送失败：员工不是试用期，empId：{}", empId);
                return false;
            }
            return true;
        }
        return false;
    }

    @Override
    public void personnelSendWeChat(String empName, int size, String companyName, List<String> userIdList, Boolean isFixedNotice,
                                    String noticeTypeCode, TokenUser tokenUser) {
        // keyword1
        String title = "";
        String type = "";
        switch (noticeTypeCode) {
            case NoticeConstants.PRE_TURN_OFFICIAL:
                title = "人员待转正";
                type = "待转正";
                break;

            case NoticeConstants.RESIGN:
                title = "人员离职";
                type = "离职";
                break;
            case NoticeConstants.PRE_RESIGN:
                title = "人员待离职";
                type = "待离职";
                break;

            case NoticeConstants.PRE_TRANSFER:
                title = "人员待调岗";
                type = "待调岗";
                break;

            case NoticeConstants.INDUCTION:
                title = "人员入职";
                type = "入职";
                break;
            case NoticeConstants.PRE_INDUCTION:
                title = "待入职提醒";
                type = "待入职";
                break;
            case NoticeConstants.RETIRE:
                title = "退休提醒";
                type = "退休";
                break;

            default:
                break;
        }
        String siteId = tokenUser.getSiteId();
        String content;
        if (Boolean.TRUE.equals(isFixedNotice) || size > 1) {
            content = empName + " 等" + size + "人" + " " + type;
        } else {
            content = empName + " " + type;
        }
        // 发送通知
        String appid = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_APPID_ADMIN, siteId);
        // 通知模板id
        String templateId = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_TODO_REMINDER_ADMIN, siteId);
        for (String userId : userIdList) {
            UnionOpenIdDO unionOpenIdDO = userProviderService.getUnionOpenByUserId(appid, userId);
            if (Objects.isNull(unionOpenIdDO) || StringUtils.isBlank(unionOpenIdDO.getOpenId())) {
                log.error("发送失败：查询不到UnionOpenIdDO信息，appid：{}，userId：{}", appid, userId);
            } else {
                UserDO userDO = userProviderService.selectUserById(userId);
                // 推送微信模板消息
                WeiXinDTO weiXinDTO = new WeiXinDTO();
                weiXinDTO.setAppId(appid);
                weiXinDTO.setTemplateId(templateId);
                weiXinDTO.setToUser(unionOpenIdDO.getOpenId());
                // 参数
                List<WxTemplateParam> paramList = new ArrayList<>();
                WxTemplateParam param1 = new WxTemplateParam();
                param1.setName("first");
                if (NoticeConstants.INDUCTION.equals(noticeTypeCode)) {
                    param1.setValue("您好，您有员工已入职「" + companyName + "」");
                } else if (NoticeConstants.RESIGN.equals(noticeTypeCode)) {
                    param1.setValue("您好，您有员工已离职「" + companyName + "」");
                } else {
                    param1.setValue("您好，您有未处理事项，请及时处理「" + companyName + "」");
                }
                paramList.add(param1);
                WxTemplateParam param2 = new WxTemplateParam();
                param2.setName("keyword1");
                param2.setValue(title);
                paramList.add(param2);
                WxTemplateParam param3 = new WxTemplateParam();
                param3.setName("keyword2");
                param3.setValue(content);
                paramList.add(param3);
                WxTemplateParam param4 = new WxTemplateParam();
                param4.setName("keyword3");
                param4.setValue(userDO.getName());
                paramList.add(param4);
                WxTemplateParam param5 = new WxTemplateParam();
                param5.setName("keyword4");
                param5.setValue(DateKit8.getCurrentDay(DateKit8.DATE));
                paramList.add(param5);

                WxTemplateParam param6 = new WxTemplateParam();
                param6.setName("remark");
                param6.setValue("请及时处理。");
                paramList.add(param6);
                weiXinDTO.setTemplateParamList(paramList);
                // 所有的人事通知都不跳转
                log.info(title + "发微信");
                messageProviderService.sendWeChatTempMessage(weiXinDTO, tokenUser);
            }
        }
    }

    @Override
    public void contractSendWeChat(String empName, int size, String companyName, List<String> userIdList, Boolean isFixedNotice, TokenUser tokenUser) {
        String siteId = tokenUser.getSiteId();
        String content;
        if (Boolean.TRUE.equals(isFixedNotice)) {
            content = empName + " 等" + size + "人";
        } else {
            content = empName;
        }
        // 发送通知
        String appid = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_APPID_ADMIN, siteId);
        for (String userId : userIdList) {
            UnionOpenIdDO unionOpenIdDO = userProviderService.getUnionOpenByUserId(appid, userId);
            if (Objects.isNull(unionOpenIdDO) || StringUtils.isBlank(unionOpenIdDO.getOpenId())) {
                log.error("发送失败：查询不到UnionOpenIdDO信息，appid：{}，userId：{}", appid, userId);
            } else {
                // 推送微信模板消息
                WeiXinDTO weiXinDTO = new WeiXinDTO();
                weiXinDTO.setAppId(appid);
                // 通知模板id
                String templateId = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_TODO_REMINDER_ADMIN, siteId);
                weiXinDTO.setTemplateId(templateId);
                weiXinDTO.setToUser(unionOpenIdDO.getOpenId());
                // 参数
                List<WxTemplateParam> paramList = new ArrayList<>();
                WxTemplateParam param1 = new WxTemplateParam();
                param1.setName("first");
                param1.setValue("您好，您有未处理事项，请及时处理「" + companyName + "」");
                paramList.add(param1);
                WxTemplateParam param2 = new WxTemplateParam();
                param2.setName("keyword1");
                param2.setValue("合同续签");
                paramList.add(param2);
                WxTemplateParam param3 = new WxTemplateParam();
                param3.setName("keyword2");
                param3.setValue("合同续签");
                paramList.add(param3);
                WxTemplateParam param4 = new WxTemplateParam();
                param4.setName("keyword3");
                param4.setValue(content);
                paramList.add(param4);
                WxTemplateParam param5 = new WxTemplateParam();
                param5.setName("keyword4");
                param5.setValue(DateKit8.getCurrentDay(DateKit8.DATE));
                paramList.add(param5);

                WxTemplateParam param6 = new WxTemplateParam();
                param6.setName("remark");
                param6.setValue("请及时处理。点击查看详情");
                paramList.add(param6);

                weiXinDTO.setTemplateParamList(paramList);
                // 跳转小程序
                WxMiNiParam wxMiNiParam = new WxMiNiParam();
                // 小程序appid配置
                String miniAppid = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_MINI_APPID, siteId);
                // 小程序首页配置
                String pagePath = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_MINI_PAGE_PATH, siteId);
                wxMiNiParam.setAppid(miniAppid);
                wxMiNiParam.setPagepath(pagePath);
                weiXinDTO.setMiniProgram(wxMiNiParam);
                log.info("合同到期发微信");
                messageProviderService.sendWeChatTempMessage(weiXinDTO, tokenUser);
            }
        }
    }

    /**
     * 发送社保相关通知
     */
    @Override
    public void sendIncreaseDecreaseNotice(String empId, String companyId, int increaseDecreaseCount, Boolean sourceSoc) {
        NoticeRuleSettingVO ruleSettingVO = noticeProviderService.selectByTypeCodeAndCompany(HrConstants.HR_SUBJECT_TYPE,
                NoticeConstants.INCREMENT, companyId);
        if (sourceSoc && ReceiveDateTypeEnum.FIXED.getValue().equals(ruleSettingVO.getReceiveDateType())) {
            return;
        }
        EmpInfoDO empInfoDO = empInfoService.selectById(empId);
        if (Objects.nonNull(ruleSettingVO)) {
            String empType = ruleSettingVO.getEmpType();
            TokenUser tokenUser = new TokenUser();
            tokenUser.setUserId(empInfoDO.getCreateUserId());
            tokenUser.setSiteId(empInfoDO.getSiteId());
            // 有公司权限的用户列表
            List<String> userIdList = NoticeKit.getNoticeUserId(empId, ruleSettingVO, tokenUser);
            if (CollectionUtils.isEmpty(userIdList)) {
                log.info("通知设置userId不存在, code: {},接收人员类型: {}, 用工单位id: {}", NoticeConstants.INCREMENT, empType, companyId);
                return;
            }
            CompanyDO companyDO = companyService.selectDOById(empInfoDO.getCompanyId(), empInfoDO.getSiteId());
            if (!ruleSettingVO.getEnableStatus()) {
                log.info("通知设置未开启, code: {},接收人员类型: {}, 用工单位id: {}", NoticeConstants.INCREMENT, empType, companyId);
                return;
            }
            // 通知类型
            String receiveType = ruleSettingVO.getReceiveType();
            // 社保增减员发送通知
            List<String> receiveTypeList = Arrays.asList(receiveType.split(","));
            if (receiveTypeList.contains(WayType.WEIXIN.getValue())) {
                // 向管理员发送微信
                sendIncreaseDecreaseWeChat(empInfoDO.getName(), companyDO.getName(),
                        increaseDecreaseCount, userIdList, tokenUser);
            }
            if (receiveTypeList.contains(WayType.SYSTEM.getValue())) {
                String toUrl = "";
                if (increaseDecreaseCount == 1) {
                    toUrl = TO_URL_SOC + "?searchName=" + empInfoDO.getName();
                }
                // 用户通知
                batchSaveByCode(userIdList, NoticeConstants.INCREMENT, ruleSettingVO.getNoticeTypeId(), companyId,
                        empInfoDO.getName(), increaseDecreaseCount, companyDO.getName(), toUrl, tokenUser);
            }
        }
    }

    @Override
    public void sendContractExpireNotice(TaskDO task, String contractIds, String noticeTypeCode, Boolean isFixedNotice) {
        String[] split = contractIds.split(",");
        if (StrKit.isEmpty(split)) {
            return;
        }
        List<String> contractIdList = Arrays.asList(split);
        int size = contractIdList.size();


        // 电子合同-》花名册纸质合同-》花名册电子合同
        ContractDO contractDO;
        String contractId = contractIdList.get(0);
        Long contractId1 = SafeKit.getLong(contractId);
        String empId = null;
        if (contractId1 != null) {
            contractDO = contractProviderService.selectById(contractId1);
            // 根据合同信息查询empId
            EmpInfoDO empInfoDO = contractProviderService.selectEmpInfoByContractId(contractDO.getId());
            if (empInfoDO != null) {
                empId = empInfoDO.getId();
            } else {
                log.info("查询不到员工id，合同id：{}", contractDO.getId());
            }
        } else {
            EmpPaperContractDO empPaperContractDO = empPaperContractService.selectDOById(contractId);
            if (empPaperContractDO == null) {
                EmpContractDO empContractDO = empContractService.selectDOById(contractId);
                if (empContractDO == null) {
                    log.info("合同到期提醒，查询不到合同信息，合同id：{}", contractId);
                    return;
                }
                contractDO = new ContractDO();
                contractDO.setSubjectId(empContractDO.getCompanyId());
                contractDO.setSiteId(empContractDO.getSiteId());
                EmpInfoDO empInfoDO = empInfoService.selectById(empContractDO.getEmpId());
                if (empInfoDO == null) {
                    log.info("合同到期提醒，员工信息不存在，empId：{}", empContractDO.getEmpId());
                    return;
                }
                empId = empInfoDO.getId();
                contractDO.setPartyBName(empInfoDO.getName());
            } else {
                contractDO = new ContractDO();
                contractDO.setSubjectId(empPaperContractDO.getCompanyId());
                contractDO.setSiteId(empPaperContractDO.getSiteId());
                EmpInfoDO empInfoDO = empInfoService.selectById(empPaperContractDO.getEmpId());
                if (empInfoDO == null) {
                    log.info("合同到期提醒，员工信息不存在，empId：{}", empPaperContractDO.getEmpId());
                    return;
                }
                empId = empInfoDO.getId();
                contractDO.setPartyBName(empInfoDO.getName());
            }
        }

        String empName = contractDO.getPartyBName();

        String siteId = contractDO.getSiteId();
        TokenUser tokenUser = new TokenUser();
        tokenUser.setUserId("system");
        tokenUser.setSiteId(siteId);
        CompanyVO companyVO = companyService.selectBaseCompanyById(contractDO.getSubjectId(), tokenUser.getSiteId());
        String companyId = companyVO.getId();
        NoticeRuleSettingVO ruleSettingVO = noticeProviderService.selectByTypeCodeAndCompany(HrConstants.HR_SUBJECT_TYPE,
                noticeTypeCode, companyId);

        if (Objects.nonNull(ruleSettingVO)) {

            // 有公司权限的用户列表
            List<String> userIdList = NoticeKit.getNoticeUserId(empId, ruleSettingVO, tokenUser);
            if (CollectionUtils.isEmpty(userIdList)) {
                log.info("通知设置userId不存在, code: {}, 用工单位id: {}", noticeTypeCode, companyId);
                return;
            }
            // 未开启则不通知
            if (!ruleSettingVO.getEnableStatus()) {
                log.info("通知设置未开启, code: {}, 用工单位id: {}", noticeTypeCode, companyId);
                return;
            }
            // 通知类型
            String receiveType = ruleSettingVO.getReceiveType();
            List<String> receiveTypeList = Arrays.asList(receiveType.split(","));
            if (receiveTypeList.contains(WayType.WEIXIN.getValue())) {
                contractSendWeChat(empName, size, companyVO.getName(), userIdList, isFixedNotice, tokenUser);
            }
            if (receiveTypeList.contains(WayType.SYSTEM.getValue())) {
                String toUrl = "";
                if (!Boolean.TRUE.equals(isFixedNotice)) {
                    toUrl = TO_URL_CONTRACT + "?immediatelyMaturityCountId=5&contractNameOrNoOrSignNo=" + contractDO.getPartyBName();
                }
                // 用户通知
                batchSaveByCode(userIdList, noticeTypeCode, ruleSettingVO.getNoticeTypeId(), companyId,
                        empName, size, companyVO.getName(), toUrl, tokenUser);
            }
        }
    }

    /**
     * 发送社保相关微信
     */
    public void sendIncreaseDecreaseWeChat(String empName, String companyName, int increaseDecreaseCount,
                                           List<String> userList, TokenUser tokenUser) {
        // 公众号appId配置
        String appId = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_APPID_ADMIN, tokenUser.getSiteId());
        for (String userId : userList) {
            UnionOpenIdDO unionOpenIdDO = userProviderService.getUnionOpenByUserId(appId, userId);
            if (Objects.isNull(unionOpenIdDO) || StringUtils.isBlank(unionOpenIdDO.getOpenId())) {
                log.error("发送失败：查询不到UnionOpenIdDO信息，appid：{}，userId：{}", appId, userId);
            } else {
                UserDO userDO = userProviderService.selectUserById(userId);
                // 推送微信模板消息
                WeiXinDTO weiXinDTO = new WeiXinDTO();
                weiXinDTO.setAppId(appId);
                // 通知模板id
                String templateId = siteConfigProviderService
                        .selectValueByCode(ConfigCodeConstants.CODE_TODO_REMINDER_ADMIN, tokenUser.getSiteId());
                weiXinDTO.setTemplateId(templateId);
                weiXinDTO.setToUser(unionOpenIdDO.getOpenId());
                // 参数
                List<WxTemplateParam> paramList = new ArrayList<>();
                // 前缀
                WxTemplateParam param1 = new WxTemplateParam();
                param1.setName("first");
                param1.setValue("您好,您有未处理事项,请及时处理[" + companyName + "]");
                paramList.add(param1);
                // 事项名称
                WxTemplateParam param2 = new WxTemplateParam();
                param2.setName("keyword1");
                param2.setValue("社保增减员待确认");
                paramList.add(param2);
                // 事项摘要
                WxTemplateParam param3 = new WxTemplateParam();
                param3.setName("keyword2");
                if (increaseDecreaseCount > 1) {
                    param3.setValue("【" + empName + "】" + "等" + increaseDecreaseCount + "人社保增减员待确认");
                } else {
                    param3.setValue("【" + empName + "】" + "社保增减员待确认");
                }
                paramList.add(param3);
                // 处理人
                WxTemplateParam param4 = new WxTemplateParam();
                param4.setName("keyword3");
                param4.setValue(userDO.getName());
                paramList.add(param4);
                // 时间
                WxTemplateParam param5 = new WxTemplateParam();
                param5.setName("keyword4");
                param5.setValue(DateUtils.getYearMonthByDate(new Date()));
                paramList.add(param5);
                // 后缀
                WxTemplateParam param6 = new WxTemplateParam();
                param6.setName("remark");
                param6.setValue("请及时处理。");
                paramList.add(param6);

                weiXinDTO.setTemplateParamList(paramList);
                messageProviderService.sendWeChatTempMessage(weiXinDTO, tokenUser);
            }
        }
    }

    /**
     * 发送甲方合同到期相关通知
     */
    @Override
    public void sendJfContractNotice(String companyId, String subjectId) {
        CompanyDO companyDO = companyService.selectDOByIdNotSite(companyId);
        CompanySaleServerDO companySaleServer = companySaleServerService.selectDOById(subjectId, companyDO.getSiteId());
        if (ObjectUtils.isEmpty(companySaleServer)) {
            log.error("甲方合同已被删除");
            return;
        }
        NoticeRuleSettingVO ruleSettingVO = noticeProviderService.selectByTypeCodeAndCompany(HrConstants.HR_SUBJECT_TYPE,
                NoticeConstants.JF_CONTRACT, companyId);
        if (Objects.nonNull(ruleSettingVO)) {
            TokenUser tokenUser = new TokenUser();
            tokenUser.setUserId(companyDO.getCreateUserId());
            tokenUser.setSiteId(companyDO.getSiteId());
            String empType = ruleSettingVO.getEmpType();
            // 有公司权限的用户列表
            List<String> userIdList = NoticeKit.getNoticeUserId(null, ruleSettingVO, tokenUser);
            if (CollectionUtils.isEmpty(userIdList)) {
                log.info("通知设置userId不存在, code: {},接收人员类型: {}, 用工单位id: {}", NoticeConstants.INCREMENT, empType, companyId);
                return;
            }
            if (!ruleSettingVO.getEnableStatus()) {
                log.info("通知设置未开启, code: {},接收人员类型: {}, 用工单位id: {}", NoticeConstants.INCREMENT, empType, companyId);
                return;
            }
            // 接收方式
            String receiveType = ruleSettingVO.getReceiveType();
            // 服务反馈发送通知
            List<String> receiveTypeList = Arrays.asList(receiveType.split(","));
            if (receiveTypeList.contains(WayType.WEIXIN.getValue())) {
                // 向管理员发送微信
                sendJfContractWeChat(userIdList, tokenUser);
            }
            if (receiveTypeList.contains(WayType.SYSTEM.getValue())) {
                String toUrl = TO_URL_JF_CONTRACT + companyId;
                // 用户通知
                batchSaveByCode(userIdList, NoticeConstants.JF_CONTRACT, ruleSettingVO.getNoticeTypeId(), companyId,
                        null, 0, companyDO.getName(), toUrl, tokenUser);
            }
        }
    }

    /**
     * 发送甲方合同到期微信
     */
    public void sendJfContractWeChat(List<String> userList, TokenUser tokenUser) {
        List<UserDO> users = userProviderService.selectUserByIds(userList);
        Map<String, UserDO> userMap = users.stream().collect(Collectors.toMap(UserDO::getId, v -> v));
        // 通知的时间只精确到了分,所以这里需要截取一下
        String gmtCreateStr = DateKit8.format2DateTime(new Date());
        gmtCreateStr = gmtCreateStr.substring(0, gmtCreateStr.lastIndexOf(":"));
        // 公众号appId配置
        String appId = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_APPID_ADMIN, tokenUser.getSiteId());
        for (String userId : userList) {
            UserDO user = userMap.get(userId);
            UnionOpenIdDO unionOpenIdDO = userProviderService.getUnionOpenByUserId(appId, userId);
            if (Objects.isNull(unionOpenIdDO) || StringUtils.isBlank(unionOpenIdDO.getOpenId())) {
                log.error("发送失败：查询不到UnionOpenIdDO信息，appid：{}，userId：{}", appId, userId);
            } else {
                // 推送微信模板消息
                WeiXinDTO weiXinDTO = new WeiXinDTO();
                weiXinDTO.setAppId(appId);
                // 通知模板id
                String templateId = siteConfigProviderService
                        .selectValueByCode(ConfigCodeConstants.CODE_EVENT_HANDLING_ADMIN, tokenUser.getSiteId());
                weiXinDTO.setTemplateId(templateId);
                weiXinDTO.setToUser(unionOpenIdDO.getOpenId());
                // 参数
                List<WxTemplateParam> paramList = new ArrayList<>();
                // 前缀
                WxTemplateParam param1 = new WxTemplateParam();
                param1.setName("first");
                param1.setValue("您好，您有一个甲方合同即将到期，请及时续约");
                paramList.add(param1);
                // 事项名称
                WxTemplateParam param2 = new WxTemplateParam();
                param2.setName("keyword1");
                param2.setValue("甲方合同到期提醒");
                paramList.add(param2);
                // 事项摘要
                WxTemplateParam param3 = new WxTemplateParam();
                param3.setName("keyword2");
                param3.setValue("甲方合同即将到期");
                paramList.add(param3);
                // 处理人
                WxTemplateParam param4 = new WxTemplateParam();
                param4.setName("keyword3");
                param4.setValue(user.getName());
                paramList.add(param4);
                // 时间
                WxTemplateParam param5 = new WxTemplateParam();
                param5.setName("keyword4");
                param5.setValue(gmtCreateStr);
                paramList.add(param5);
                // 后缀
                WxTemplateParam param6 = new WxTemplateParam();
                param6.setName("remark");
                param6.setValue("请去pc端 对应用工单位查看合同详情");
                paramList.add(param6);

                weiXinDTO.setTemplateParamList(paramList);
                messageProviderService.sendWeChatTempMessage(weiXinDTO, tokenUser);
            }
        }
    }

    /**
     * 发送事件处理(服务反馈)相关通知
     */
    @Override
    public void sendEventHandlingNotice(String companyId, EventHandlingDO eventHandling, TokenUser tokenUser) {
        NoticeRuleSettingVO ruleSettingVO = noticeProviderService.selectByTypeCodeAndCompany(HrConstants.HR_SUBJECT_TYPE,
                NoticeConstants.EVENT_HANDLING, companyId);
        if (Objects.nonNull(ruleSettingVO)) {
            // 服务反馈提醒  只提供实时
            if (!ReceiveDateTypeEnum.RIGHT_NOW.getValue().equals(ruleSettingVO.getReceiveDateType())) {
                return;
            }
            String empType = ruleSettingVO.getEmpType();
            // 有公司权限的用户列表
            List<String> userIdList = NoticeKit.getNoticeUserId(null, ruleSettingVO, tokenUser);
            if (CollectionUtils.isEmpty(userIdList)) {
                log.info("通知设置userId不存在, code: {},接收人员类型: {}, 用工单位id: {}", NoticeConstants.INCREMENT, empType, companyId);
                return;
            }
            CompanyDO companyDO = companyService.selectDOById(companyId, tokenUser.getSiteId());
            if (!ruleSettingVO.getEnableStatus()) {
                log.info("通知设置未开启, code: {},接收人员类型: {}, 用工单位id: {}", NoticeConstants.INCREMENT, empType, companyId);
                return;
            }
            // 接收方式
            String receiveType = ruleSettingVO.getReceiveType();
            // 服务反馈发送通知
            List<String> receiveTypeList = Arrays.asList(receiveType.split(","));
            if (receiveTypeList.contains(WayType.WEIXIN.getValue())) {
                UserDO userDO = userProviderService.selectUserById(eventHandling.getCreateUserId());
                String userName = ObjectUtils.isEmpty(userDO) ? "" : userDO.getName();
                // 向管理员发送微信
                sendEventHandlingWeChat(eventHandling, userName, userIdList, tokenUser);
            }
            if (receiveTypeList.contains(WayType.SYSTEM.getValue())) {
                // 用户通知
                batchSaveByCode(userIdList, NoticeConstants.EVENT_HANDLING, ruleSettingVO.getNoticeTypeId(), companyId,
                        eventHandling.getEventTitle(), 0, companyDO.getName(), TO_URL_EVENT_HANDLING, tokenUser);
            }
        }
    }

    /**
     * 发送甲方合同到期微信
     */
    public void sendEventHandlingWeChat(EventHandlingDO eventHandling, String createEventUserName,
                                        List<String> userList, TokenUser tokenUser) {
        // 通知的时间只精确到了分,所以这里需要截取一下
        Date gmtCreate = eventHandling.getGmtCreate();
        String gmtCreateStr = DateKit8.format2DateTime(gmtCreate);
        gmtCreateStr = gmtCreateStr.substring(0, gmtCreateStr.lastIndexOf(":"));
        // 公众号appId配置
        String appId = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_APPID_ADMIN, tokenUser.getSiteId());
        // 文案
        String eventHandlingCopyWriting = siteConfigProviderService
                .selectValueByCode(ConfigCodeConstants.EVENT_HANDLING_COPY_WRITING, tokenUser.getSiteId());
        for (String userId : userList) {
            UnionOpenIdDO unionOpenIdDO = userProviderService.getUnionOpenByUserId(appId, userId);
            if (Objects.isNull(unionOpenIdDO) || StringUtils.isBlank(unionOpenIdDO.getOpenId())) {
                log.error("发送失败：查询不到UnionOpenIdDO信息，appid：{}，userId：{}", appId, userId);
            } else {
                // 推送微信模板消息
                WeiXinDTO weiXinDTO = new WeiXinDTO();
                weiXinDTO.setAppId(appId);
                // 通知模板id
                String templateId = siteConfigProviderService
                        .selectValueByCode(ConfigCodeConstants.CODE_EVENT_HANDLING_ADMIN, tokenUser.getSiteId());
                weiXinDTO.setTemplateId(templateId);
                weiXinDTO.setToUser(unionOpenIdDO.getOpenId());
                // 参数
                List<WxTemplateParam> paramList = new ArrayList<>();
                // 前缀
                WxTemplateParam param1 = new WxTemplateParam();
                param1.setName("first");
                param1.setValue("您好，您有一条服务通知请及时查看");
                paramList.add(param1);
                // 事项名称
                WxTemplateParam param2 = new WxTemplateParam();
                param2.setName("keyword1");
                param2.setValue(eventHandling.getEventTitle());
                paramList.add(param2);
                // 事项摘要
                WxTemplateParam param3 = new WxTemplateParam();
                param3.setName("keyword2");
                param3.setValue(eventHandling.getEventLabel());
                paramList.add(param3);
                // 处理人
                WxTemplateParam param4 = new WxTemplateParam();
                param4.setName("keyword3");
                param4.setValue(createEventUserName);
                paramList.add(param4);
                // 时间
                WxTemplateParam param5 = new WxTemplateParam();
                param5.setName("keyword4");
                param5.setValue(gmtCreateStr);
                paramList.add(param5);
                // 后缀
                WxTemplateParam param6 = new WxTemplateParam();
                param6.setName("remark");
                param6.setValue(eventHandlingCopyWriting);
                paramList.add(param6);

                weiXinDTO.setTemplateParamList(paramList);

                // 跳转小程序
                WxMiNiParam wxMiNiParam = new WxMiNiParam();
                // 小程序appid配置
                String miniAppid = siteConfigProviderService
                        .selectValueByCode(ConfigCodeConstants.CODE_JF_MINI_APPID, tokenUser.getSiteId());
                // 小程序首页配置
                String pagePath = siteConfigProviderService
                        .selectValueByCode(ConfigCodeConstants.PAGE_PATH_EVENT_HANDLING_JF_MINI, tokenUser.getSiteId());
                wxMiNiParam.setAppid(miniAppid);
                wxMiNiParam.setPagepath(pagePath);
                weiXinDTO.setMiniProgram(wxMiNiParam);
                log.info("服务反馈发微信");
                messageProviderService.sendWeChatTempMessage(weiXinDTO, tokenUser);
            }
        }
    }

    /**
     * 保存个人通知
     */
    private void batchSaveByCode(List<String> userIdList, String noticeTypeCode, Long typeId, String companyId,
                                 String empName, int size, String companyName, String toUrl, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(userIdList)) {
            return;
        }
        String title = "";
        String content = "";
        switch (noticeTypeCode) {
            case NoticeConstants.INDUCTION:
                title = "人员入职";
                content = empName + " 等" + size + "名员工入职，请及时处理";
                break;
            case NoticeConstants.PRE_INDUCTION:
                title = "人员待入职";
                content = empName + " 等" + size + "名员工待入职，请及时处理";
                break;
            case NoticeConstants.PRE_TURN_OFFICIAL:
                title = "人员待转正";
                content = empName + " 等" + size + "名员工待转正，请及时处理";
                break;
            case NoticeConstants.PRE_TRANSFER:
                title = "人员待调岗";
                content = empName + " 等" + size + "名员工待调岗，请及时处理";
                break;
            case NoticeConstants.PRE_RESIGN:
                title = "人员待离职";
                content = empName + " 等" + size + "名员工待离职，请及时处理";
                break;
            case NoticeConstants.RESIGN:
                title = "人员离职";
                content = empName + " 等" + size + "名员工离职，请及时处理";
                break;
            case NoticeConstants.CONTRACT_EXPIRES:
                title = "合同到期";
                content = empName + " 等" + size + "名员工合同即将到期，请及时处理";
                break;
            case NoticeConstants.INCREMENT:
                title = "增减员确认";
                content = empName + " 等" + size + "名员工社保增减员待确认，请及时处理";
                break;

            case NoticeConstants.RETIRE:
                title = "退休提醒";
                content = empName + " 等" + size + "名员工即将退休，请及时处理";
                break;

            case NoticeConstants.SALARY_CARD_CHANGE:
                title = "工资卡信息变更";
                content = empName + " 工资卡信息发生改动，请及时处理";
                break;
            case NoticeConstants.EVENT_HANDLING:
                title = "服务反馈";
                content = empName + " 已创建，请及时处理";
                break;
            case NoticeConstants.JF_CONTRACT:
                title = "甲方合同到期";
                content = "甲方合同即将到期 请及时处理";
                break;
            default:
                break;
        }

        List<UserNoticeAddDTO> userNoticeAddList = new ArrayList<>();
        for (String userId : userIdList) {
            UserNoticeAddDTO userNoticeAddDTO = new UserNoticeAddDTO();
            userNoticeAddDTO.setUserId(userId);
            userNoticeAddDTO.setModuleType(HrConstants.HR_SUBJECT_TYPE);
            userNoticeAddDTO.setNoticeTypeId(typeId);
            userNoticeAddDTO.setNoticeTypeCode(noticeTypeCode);
            userNoticeAddDTO.setWayType("");
            userNoticeAddDTO.setTitle(title);
            userNoticeAddDTO.setContent(content);
            userNoticeAddDTO.setToUrl(toUrl);
            userNoticeAddDTO.setSubjectType(noticeTypeCode);
            userNoticeAddDTO.setSubjectId(companyId);
            userNoticeAddDTO.setCompanyName(companyName);
            userNoticeAddDTO.setCreateUserName("系统");
            userNoticeAddList.add(userNoticeAddDTO);
        }
        noticeProviderService.batchSaveByCode(userNoticeAddList, typeId, tokenUser);
    }

    @Override
    public void memoRemindSendNotice(String companyId, MemoInfoDO memoInfoDO, TokenUser tokenUser) {
        String userId = memoInfoDO.getCreateUserId();
        NoticeRuleSettingVO ruleSettingVO = noticeProviderService.selectByTypeCodeAndCompany(HrConstants.HR_SUBJECT_TYPE,
                NoticeConstants.MEMO_REMIND, companyId);
        if (Objects.isNull(ruleSettingVO)) {
            return;
        }
        // 未开启则不通知
        if (!ruleSettingVO.getEnableStatus()) {
            return;
        }
        String companyName = "";
        CompanyDO companyDO = companyService.selectDOById(companyId, tokenUser.getSiteId());
        if (!ObjectUtils.isEmpty(companyDO)) {
            companyName = companyDO.getName();
        }
        // 有公司权限的用户列表
        List<String> userIdList = new ArrayList<>();
        String empType = ruleSettingVO.getEmpType();
        if (EmpType.SELF.getValue().equals(empType)) {
            userIdList = Collections.singletonList(userId);
        }
        if (CollectionUtils.isEmpty(userIdList)) {
            return;
        }
        // 通知类型
        String receiveType = ruleSettingVO.getReceiveType();
        List<String> receiveTypeList = Arrays.asList(receiveType.split(","));
        if (receiveTypeList.contains(WayType.WEIXIN.getValue())) {
            // 发微信
            memoInfoSendWeChat(companyId, memoInfoDO, userIdList, tokenUser);
        }
        if (receiveTypeList.contains(WayType.SYSTEM.getValue())) {
            // 备忘录提醒发送消息通知
            noticeProviderService.memoRemindNoticeSend(memoInfoDO.getCompanyId(), memoInfoDO.getContent(), companyName, tokenUser);

        }
    }

    @Override
    public void salaryCardChangeSendWeChat(EmpInfoDO empInfo, List<String> userList, TokenUser tokenUser) {
        // 公众号appid配置
        String appid = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_APPID_ADMIN,
                tokenUser.getSiteId());
        for (String userId : userList) {
            UnionOpenIdDO unionOpenIdDO = userProviderService.getUnionOpenByUserId(appid, userId);
            if (Objects.isNull(unionOpenIdDO) || StringUtils.isBlank(unionOpenIdDO.getOpenId())) {
                log.error("发送失败：查询不到UnionOpenIdDO信息，appid：{}，userId：{}", appid, userId);
            } else {
                CompanyVO companyVO = companyService.selectBaseCompanyById(empInfo.getCompanyId(), tokenUser.getSiteId());
                // 推送微信模板消息
                WeiXinDTO weiXinDTO = new WeiXinDTO();
                weiXinDTO.setAppId(appid);
                // 通知模板id
                String templateId = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_EMPINFO_CHANGE_ADMIN,
                        tokenUser.getSiteId());
                weiXinDTO.setTemplateId(templateId);
                weiXinDTO.setToUser(unionOpenIdDO.getOpenId());
                // 参数
                List<WxTemplateParam> paramList = new ArrayList<>();
                WxTemplateParam param1 = new WxTemplateParam();
                param1.setName("first");
                param1.setValue("您有一名员工工资卡信息发生改动「" + companyVO.getName() + "」");
                paramList.add(param1);
                WxTemplateParam param2 = new WxTemplateParam();
                param2.setName("keyword1");
                param2.setValue(empInfo.getName());
                paramList.add(param2);
                WxTemplateParam param3 = new WxTemplateParam();
                param3.setName("keyword2");
                param3.setValue(DateKit8.getCurrentDay(DateKit8.DATE_TIME));
                paramList.add(param3);
                WxTemplateParam param4 = new WxTemplateParam();
                param4.setName("keyword3");
                param4.setValue(tokenUser.getUserName());
                paramList.add(param4);
                WxTemplateParam param5 = new WxTemplateParam();
                param5.setName("remark");
                param5.setValue("请您及时登录系统进行确认");
                paramList.add(param5);

                weiXinDTO.setTemplateParamList(paramList);
                /*// 跳转小程序
                WxMiNiParam wxMiNiParam = new WxMiNiParam();
                // 小程序appid配置
                String miniAppid = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_MINI_APPID,
                        tokenUser.getSiteId());
                // 小程序首页配置
                String pagePath = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_MINI_PAGE_PATH,
                        tokenUser.getSiteId());
                wxMiNiParam.setAppid(miniAppid);
                wxMiNiParam.setPagepath(pagePath);
                weiXinDTO.setMiniProgram(wxMiNiParam);*/
                messageProviderService.sendWeChatTempMessage(weiXinDTO, tokenUser);
            }
        }
    }

    @Override
    public void memoInfoSendWeChat(String companyId, MemoInfoDO memoInfoDO, List<String> userIdList, TokenUser tokenUser) {
        String siteId = tokenUser.getSiteId();
        String appid = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_APPID_ADMIN, siteId);
        for (String userId : userIdList) {
            UnionOpenIdDO unionOpenIdDO = userProviderService.getUnionOpenByUserId(appid, userId);
            if (Objects.isNull(unionOpenIdDO) || StringUtils.isBlank(unionOpenIdDO.getOpenId())) {
                log.error("发送失败：查询不到UnionOpenIdDO信息，appid：{}，userId：{}", appid, userId);
            } else {
                CompanyVO companyVO = companyService.selectBaseCompanyById(companyId, tokenUser.getSiteId());
                // 推送微信模板消息
                WeiXinDTO weiXinDTO = new WeiXinDTO();
                weiXinDTO.setAppId(appid);
                // 通知模板id
                String templateId = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_TODO_REMINDER_ADMIN, siteId);
                weiXinDTO.setTemplateId(templateId);
                weiXinDTO.setToUser(unionOpenIdDO.getOpenId());
                // 参数
                List<WxTemplateParam> paramList = new ArrayList<>();
                WxTemplateParam param1 = new WxTemplateParam();
                param1.setName("first");
                param1.setValue("您好，您有未处理事项，请及时处理「" + companyVO.getName() + "」");
                paramList.add(param1);
                WxTemplateParam param2 = new WxTemplateParam();
                param2.setName("keyword1");
                param2.setValue("备忘事项");
                paramList.add(param2);
                WxTemplateParam param3 = new WxTemplateParam();
                param3.setName("keyword2");
                String content = memoInfoDO.getContent();
                if (content.length() > 20) {
                    content = content.substring(0, 19);
                }
                param3.setValue(content);
                paramList.add(param3);
                WxTemplateParam param4 = new WxTemplateParam();
                param4.setName("keyword3");
                param4.setValue(tokenUser.getUserName());
                paramList.add(param4);
                WxTemplateParam param5 = new WxTemplateParam();
                param5.setName("keyword4");
                param5.setValue(DateKit8.getCurrentDay(DateKit8.DATE));
                paramList.add(param5);

                WxTemplateParam param6 = new WxTemplateParam();
                param6.setName("remark");
                param6.setValue("点击查看详情");
                paramList.add(param6);

                weiXinDTO.setTemplateParamList(paramList);
                // 跳转小程序
                WxMiNiParam wxMiNiParam = new WxMiNiParam();
                // 小程序appid配置
                String miniAppid = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_MINI_APPID, siteId);
                // 小程序首页配置
                String pagePath = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_MINI_PAGE_PATH, siteId);
                wxMiNiParam.setAppid(miniAppid);
                wxMiNiParam.setPagepath(pagePath);
                weiXinDTO.setMiniProgram(wxMiNiParam);
                log.info("备忘录发微信");
                messageProviderService.sendWeChatTempMessage(weiXinDTO, tokenUser);
            }
        }
    }

    /**
     * 发送通知
     */
    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void salaryChangeSendNotice(EmpInfoDO empInfoChange, String companyId, TokenUser tokenUser) {
        NoticeRuleSettingVO ruleSettingVO = noticeProviderService.selectByTypeCodeAndCompany(HrConstants.HR_SUBJECT_TYPE,
                NoticeConstants.SALARY_CARD_CHANGE, companyId);
        if (Objects.isNull(ruleSettingVO)) {
            log.info("发送失败：通知设置不存在，noticeTypeCode：{},companyId:{}", NoticeConstants.SALARY_CARD_CHANGE, companyId);
            return;
        }
        if (!ruleSettingVO.getEnableStatus()) {
            log.info("发送失败：通知设置未开启, code: {}, 用工单位id: {}", NoticeConstants.SALARY_CARD_CHANGE, companyId);
            return;
        }
        String empType = ruleSettingVO.getEmpType();
        List<String> empTypeList = ArrayKit.split(empType);
        if (CollectionUtils.isEmpty(empTypeList)) {
            log.error("发送失败：接收人员类型为空，code：{},", NoticeConstants.SALARY_CARD_CHANGE);
            return;
        }
        // 有公司权限的用户列表
        List<String> userIdList = NoticeKit.getNoticeUserId(empInfoChange.getId(), ruleSettingVO, tokenUser);
        if (CollectionUtils.isEmpty(userIdList)) {
            log.error("发送失败：userIdList为空，code：{}", NoticeConstants.SALARY_CARD_CHANGE);
            return;
        }
        // 发送用户id去重
        userIdList = userIdList.stream().distinct().collect(Collectors.toList());
        // 通知类型
        String receiveType = ruleSettingVO.getReceiveType();
        // 工资卡变更实时发送
        if (ReceiveDateTypeEnum.RIGHT_NOW.getValue().equals(ruleSettingVO.getReceiveDateType())) {
            List<String> receiveTypeList = Arrays.asList(receiveType.split(","));
            if (receiveTypeList.contains(WayType.WEIXIN.getValue())) {
                // 向管理员发送微信
                salaryCardChangeSendWeChat(empInfoChange, userIdList, tokenUser);
            }
            if (receiveTypeList.contains(WayType.SYSTEM.getValue())) {
                CompanyVO companyVO = companyService.selectBaseCompanyById(companyId, tokenUser.getSiteId());
                String toUrl = "/staff/detail?userId=" + empInfoChange.getUserId() + "&id=" + empInfoChange.getId();
                // 用户通知
                batchSaveByCode(userIdList, NoticeConstants.SALARY_CARD_CHANGE, ruleSettingVO.getNoticeTypeId(),
                        companyId, empInfoChange.getName(), 1, companyVO.getName(), toUrl, tokenUser);
            }
        }

    }


    /**
     * 企业单方签署发送微信消息通知
     *
     * @param weiXinSendList 要发送的人
     * @param tokenUser      当前用户
     */
    @Override
    public void sendWaitViewWeiXinTemp(List<SignWeiXinSendDTO> weiXinSendList, TokenUser tokenUser) {
        // 用缓存来控制发不发通知
//        String sendNoticeLockKey = CacheKeyKit.getSendNoticeLockKey();
//        boolean isSend = cache.get(sendNoticeLockKey);
//        if (!ObjectUtils.isEmpty(isSend) && !isSend) {
//            log.info("缓存控制不发微信或短信通知");
//            return;
//        }
        if (ObjectUtils.isEmpty(weiXinSendList)) {
            return;
        }
        String appId = siteConfigProviderService.selectValueByCode(CODE_APPID, tokenUser.getSiteId());
        String waitSignTempId = siteConfigProviderService.selectValueByCode(CODE_WAIT_SIGN_TEMP_ID, tokenUser.getSiteId());
        String miNiAppId = siteConfigProviderService.selectValueByCode(CODE_MINI_APPID, tokenUser.getSiteId());
        String miNiPagePath = siteConfigProviderService.selectValueByCode(CODE_PATH_CONTRACTSIGN, tokenUser.getSiteId());
        // 小程序appid ,appSecret
        String appid = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_MINI_APPID, tokenUser.getSiteId());
        String secret = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_MINI_SECRET, tokenUser.getSiteId());
        String accessToken = MessageHandlerUtil.getAccessToken(appid, secret).getAccessToken();
        if (StringUtils.isEmpty(appId) || StringUtils.isEmpty(waitSignTempId)) {
            log.error("未配置微信模板id，不发送微信模板消息");
            return;
        }
        for (SignWeiXinSendDTO weiXinSend : weiXinSendList) {
            String userId = weiXinSend.getAUserId();
            UnionOpenIdDO unionOpenId = userProviderService.getUnionOpenIdByUser(userId, appId);
            if (Objects.nonNull(unionOpenId) && StringUtils.isNotEmpty(unionOpenId.getOpenId())) {
                String openId = unionOpenId.getOpenId();
                // 推送微信模板消息
                WeiXinDTO weiXinDTO = new WeiXinDTO();
                weiXinDTO.setAppId(appId);
                weiXinDTO.setTemplateId(waitSignTempId);
                weiXinDTO.setToUser(openId);
                // 参数
                List<WxTemplateParam> paramList = new ArrayList<>();
                WxTemplateParam param1 = new WxTemplateParam();
                param1.setName("first");
                param1.setValue("您好！您有一份电子合同待查看");
                paramList.add(param1);

                WxTemplateParam param2 = new WxTemplateParam();
                param2.setName("keyword1");
                param2.setValue(weiXinSend.getContractName());
                paramList.add(param2);

                WxTemplateParam param3 = new WxTemplateParam();
                param3.setName("keyword2");
                param3.setValue(weiXinSend.getAName());
                paramList.add(param3);

                WxTemplateParam param4 = new WxTemplateParam();
                param4.setName("keyword3");
                param4.setValue(weiXinSend.getBName());
                paramList.add(param4);

                WxTemplateParam param5 = new WxTemplateParam();
                param5.setName("keyword4");
                param5.setValue("");
                paramList.add(param5);

                WxTemplateParam param6 = new WxTemplateParam();
                param6.setName("keyword5");
                param6.setValue("");
                paramList.add(param6);

                weiXinDTO.setTemplateParamList(paramList);
                // 跳转小程序
                WxMiNiParam wxMiNiParam = new WxMiNiParam();
                wxMiNiParam.setAppid(miNiAppId);
                wxMiNiParam.setPagepath(miNiPagePath + "?status=3&contractId=" + weiXinSend.getContractId());
                weiXinDTO.setMiniProgram(wxMiNiParam);
                messageProviderService.sendWeChatTempMessage(weiXinDTO, tokenUser);
            } else {
                log.info("企业单方签署发送短信");
                // 跳转合同的小程序路径
                JumpWxa jumpWxa = new JumpWxa();
                jumpWxa.setPath(miNiPagePath);
                jumpWxa.setQuery("status=3&contractId=" + weiXinSend.getContractId());
                String openLink = MessageHandlerUtil.getOpenLink(accessToken, jumpWxa);
                log.info("发送短信,获取OpenLink：{}", openLink);
                openLink = openLink.substring(openLink.indexOf("t=") + 2);
                // 发不了微信通知就发短信
                log.info("发不了微信通知就发短信,userId:{}, appId：{}", userId, appId);

                sendWaitViewSms(userId, openLink, tokenUser);
            }
        }
    }

    /**
     * 异步发送有合同待签署-微信公众号或短信模板消息
     *
     * @param weiXinSendList 要发送的人
     * @param subjectName    用工单位名称
     * @param tokenUser      当前用户
     */
    @Override
    public void sendWaitSignWeiXinTemp(List<SignWeiXinSendDTO> weiXinSendList, String subjectName, TokenUser tokenUser) {
        // 测试环境直接返回 不发送通知
        // 用缓存来控制发不发通知
//        String sendNoticeLockKey = CacheKeyKit.getSendNoticeLockKey();
//        boolean isSend = cache.get(sendNoticeLockKey);
//        if (!ObjectUtils.isEmpty(isSend) && !isSend) {
//            log.info("缓存控制不发微信或短信通知");
//            return;
//        }

        if (CollectionUtils.isEmpty(weiXinSendList)) {
            return;
        }

        String appId = siteConfigProviderService.selectValueByCode(CODE_APPID, tokenUser.getSiteId());
        String waitSignTempId = siteConfigProviderService.selectValueByCode(CODE_WAIT_SIGN_TEMP_ID, tokenUser.getSiteId());
        String miNiAppId = siteConfigProviderService.selectValueByCode(CODE_MINI_APPID, tokenUser.getSiteId());
        String miNiPagePath = siteConfigProviderService.selectValueByCode(CODE_PATH_CONTRACTSIGN, tokenUser.getSiteId());

        // 小程序appid ,appSecret
        String appid = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_MINI_APPID, tokenUser.getSiteId());
        String secret = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_MINI_SECRET, tokenUser.getSiteId());
        String accessToken = MessageHandlerUtil.getAccessToken(appid, secret).getAccessToken();
        if (StringUtils.isEmpty(appId) || StringUtils.isEmpty(waitSignTempId)) {
            log.error("未配置微信模板id，不发送微信模板消息");
            return;
        }
        // 合同有效天数
        Integer expireDays = weiXinSendList.get(0).getExpireDays();

        for (SignWeiXinSendDTO weiXinSend : weiXinSendList) {
            String userId = weiXinSend.getAUserId();
            UnionOpenIdDO unionOpenId = userProviderService.getUnionOpenIdByUser(userId, appId);
            if (Objects.nonNull(unionOpenId) && StringUtils.isNotEmpty(unionOpenId.getOpenId())) {
                String openId = unionOpenId.getOpenId();
                // 推送微信模板消息
                WeiXinDTO weiXinDTO = new WeiXinDTO();
                weiXinDTO.setAppId(appId);
                weiXinDTO.setTemplateId(waitSignTempId);
                weiXinDTO.setToUser(openId);
                // 参数
                List<WxTemplateParam> paramList = new ArrayList<>();
                WxTemplateParam param1 = new WxTemplateParam();
                param1.setName("first");
                if (StrKit.isEmpty(subjectName)) {
                    param1.setValue("您好,您有一份电子合同需要签署");
                } else {
                    param1.setValue("您好,您有一份电子合同需要签署「" + subjectName + "」");
                }
                paramList.add(param1);

                WxTemplateParam param2 = new WxTemplateParam();
                param2.setName("keyword1");
                param2.setValue(weiXinSend.getContractName());
                paramList.add(param2);

                WxTemplateParam param3 = new WxTemplateParam();
                param3.setName("keyword2");
                param3.setValue(weiXinSend.getAName());
                paramList.add(param3);

                WxTemplateParam param4 = new WxTemplateParam();
                param4.setName("keyword3");
                param4.setValue(weiXinSend.getBName());
                paramList.add(param4);

                WxTemplateParam param5 = new WxTemplateParam();
                param5.setName("keyword4");
                // 无期限的先默认100天
                if (expireDays == null || expireDays == -1) {
                    param5.setValue("长期有效");
                } else {
                    Date expireDate = DateKit.getBeforeDay(new Date(), expireDays);
                    param5.setValue(DateKit.getDateTimeStr(expireDate));
                }
                paramList.add(param5);

                WxTemplateParam param6 = new WxTemplateParam();
                param6.setName("keyword5");
                param6.setValue("请在截止日期前完成签署");
                paramList.add(param6);

                weiXinDTO.setTemplateParamList(paramList);
                // 跳转小程序
                WxMiNiParam wxMiNiParam = new WxMiNiParam();
                wxMiNiParam.setAppid(miNiAppId);
                wxMiNiParam.setPagepath(miNiPagePath + "?status=0&contractId=" + weiXinSend.getContractId());
                weiXinDTO.setMiniProgram(wxMiNiParam);
                messageProviderService.sendWeChatTempMessage(weiXinDTO, tokenUser);
            } else {
                // 跳转合同的小程序路径
                JumpWxa jumpWxa = new JumpWxa();
                jumpWxa.setPath(miNiPagePath);
                jumpWxa.setQuery("status=0&contractId=" + weiXinSend.getContractId());
                String openLink = MessageHandlerUtil.getOpenLink(accessToken, jumpWxa);
                openLink = openLink.substring(openLink.indexOf("t=") + 2);
                // 发不了微信通知就发短信
                log.info("发不了微信通知就发短信,userId:{}, appId：{}", userId, appId);
                sendSms(userId, openLink, tokenUser);
            }
        }
    }

    /**
     * 发送短信
     */
    private void sendWaitViewSms(String userId, String openLink, TokenUser tokenUser) {
        UserVO userVO = userProviderService.selectById(userId);
        Map<String, Object> params = new HashMap<>(8);
        params.put("code", openLink);
        ShortMessageDTO shortMessageDTO = new ShortMessageDTO();
        shortMessageDTO.setScene(SCENE_SIGN_NOTICE_CERTIFICATION);
        // 写入短信内容
        shortMessageDTO.setPhone(userVO.getPhone());
        shortMessageDTO.setParams(params);
        try {
            messageProviderService.sendShortMessage(shortMessageDTO, tokenUser);
        } catch (Exception e) {
            log.error("合同签署发送短信失败,失败信息{}", e.getMessage());
        }
    }

    /**
     * 发送短信
     */
    private void sendSms(String userId, String openLink, TokenUser tokenUser) {
        UserVO userVO = userProviderService.selectById(userId);

        ShortMessageDTO shortMessageDTO = new ShortMessageDTO();
        Map<String, Object> params = new HashMap<>(8);
        params.put("code", openLink);
        shortMessageDTO.setScene(SCENE_SIGN_NOTICE_CERTIFICATION);
        // 写入短信内容
        shortMessageDTO.setPhone(userVO.getPhone());
        shortMessageDTO.setParams(params);
        try {
            messageProviderService.sendShortMessage(shortMessageDTO, tokenUser);
        } catch (Exception e) {
            log.error("合同签署发送短信失败,失败信息{}", e.getMessage());
        }
    }

}
